package org.testis.communication.client;

import org.testis.utils.StringUtils;
import org.testis.utils.StringVerification;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.httpclient.Credentials;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.SimpleHttpConnectionManager;
import org.apache.commons.httpclient.UsernamePasswordCredentials;
import org.apache.commons.httpclient.auth.AuthPolicy;
import org.apache.commons.httpclient.auth.AuthScope;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.params.HttpClientParams;
import org.apache.commons.httpclient.params.HttpConnectionManagerParams;

/**
 * A class to make any http related operation. This class extends from
 * apache's httpclient.
 * @author nurhat
 */
public class AtofHttpClient extends HttpClient {

    private String m_output;
    private String m_statusCode;

    public AtofHttpClient() {
        SimpleHttpConnectionManager cm = new SimpleHttpConnectionManager();
        HttpConnectionManagerParams params = new HttpConnectionManagerParams();
        params.setConnectionTimeout(20000);
        params.setSoTimeout(20000);
        cm.setParams(params);
        setHttpConnectionManager(cm);
    }

    /**
     * Check status of an http host  for availability
     * @param hostAddress
     * @return true if host available
     * @throws java.io.IOException
     */
    public boolean checkStatus(String hostAddress) {
        try {
            GetMethod httpGet =
                    new GetMethod(hostAddress);

            int status = executeMethod(httpGet);
            setStatusCode("Http Status code:" + String.valueOf(status));
            if (status == HttpStatus.SC_OK) {
                setOuput("Output:" + httpGet.getResponseBodyAsString());
                return true;
            }
            setOuput("Output:Can not connect to given site...");
            return false;
        }  catch (HttpException ex) {
            setStatusCode("Http Status code:N/A");
            setOuput("Output:HttpException occured..." + ex.toString());
        } catch (IOException ex) {
            setStatusCode("Http Status code:N/A");
            setOuput("Output:IOException occured..." + ex.toString());
        }
        return false;
    }

    /**
     * Check status of an http host  for availability
     * @param hostAddress
     * @param verifyStr
     * @return true if host available
     * @throws java.io.IOException
     */
    public boolean checkStatus(String hostAddress,
            String verifyStr) {
        try {
            GetMethod httpGet =
                    new GetMethod(hostAddress);

            int status = executeMethod(httpGet);
            setStatusCode("Http Status code:" + String.valueOf(status));
            if (status == HttpStatus.SC_OK) {
                setOuput("Output:" + httpGet.getResponseBodyAsString());
                if (!verifyStr.trim().equals("")) {
                    return StringVerification.verifyText(verifyStr,
                            getOutput());
                }
                return true;
            }
            setOuput("Output:Can not connect to given site...");
            return false;
        } catch (HttpException ex) {
            setStatusCode("Http Status code:N/A");
            setOuput("Output:HttpException occured..." + ex.toString());
        } catch (IOException ex) {
            setStatusCode("Http Status code:N/A");
            setOuput("Output:IOException occured..." + ex.toString());
        }
        return false;
    }

    /**
     * Check status of an http host  for availability with using basic 
     * authentication
     * @param hostAddress
     * @param userName
     * @param passWord
     * @return true if host available
     * @throws java.io.IOException
     */
    public boolean checkStatus(String hostHttpAddress,
            String userName,
            String passWord) {
        try {
            List<String> authPrefs = new ArrayList<String>(3);

            authPrefs.add(AuthPolicy.BASIC);
            authPrefs.add(AuthPolicy.DIGEST);
            authPrefs.add(AuthPolicy.NTLM);

            HttpClientParams param =
                    new HttpClientParams();

            param.setParameter(AuthPolicy.AUTH_SCHEME_PRIORITY,
                    authPrefs);

            Credentials defaultcreds =
                    new UsernamePasswordCredentials(userName,
                    passWord);
            getState().
                    setCredentials(new AuthScope(null,
                    80,
                    AuthScope.ANY_REALM),
                    defaultcreds);
            GetMethod httpGet = new GetMethod(hostHttpAddress);
            setParams(param);
            int status = executeMethod(httpGet);
            setStatusCode("Http Status code:" + String.valueOf(status));
            if (status == HttpStatus.SC_OK) {
                setOuput("Output:" + httpGet.getResponseBodyAsString());
                return true;
            }
            setOuput("Output:Can not connect to given site...");
            return false;
        }  catch (HttpException ex) {
            setStatusCode("Http Status code:N/A");
            setOuput("Output:HttpException occured..." + ex.toString());
        } catch (IOException ex) {
            setStatusCode("Http Status code:N/A");
            setOuput("Output:IOException occured..." + ex.toString());
        }
        return false;
    }

    /**
     * Check status of an http host  for availability with using basic 
     * authentication
     * @param hostAddress
     * @param userName
     * @param passWord
     * @param verifyStr
     * @return true if host available
     * @throws java.io.IOException
     */
    public boolean checkStatus(String hostHttpAddress,
            String userName,
            String passWord,
            String verifyStr) {
        try {
            List<String> authPrefs = new ArrayList<String>(3);

            authPrefs.add(AuthPolicy.BASIC);
            authPrefs.add(AuthPolicy.DIGEST);
            authPrefs.add(AuthPolicy.NTLM);

            HttpClientParams param =
                    new HttpClientParams();

            param.setParameter(AuthPolicy.AUTH_SCHEME_PRIORITY,
                    authPrefs);

            Credentials defaultcreds =
                    new UsernamePasswordCredentials(userName,
                    passWord);
            getState().
                    setCredentials(new AuthScope(null,
                    80,
                    AuthScope.ANY_REALM),
                    defaultcreds);
            GetMethod httpGet = new GetMethod(hostHttpAddress);
            setParams(param);
            int status = executeMethod(httpGet);
            setStatusCode("Http Status code:" + String.valueOf(status));
            if (status == HttpStatus.SC_OK) {
                setOuput("Output:" + httpGet.getResponseBodyAsString());
                if (!verifyStr.trim().equals("")) {
                    return StringVerification.verifyText(verifyStr,
                            getOutput());
                }
                return true;
            }
            setOuput("Output:Can not connect to given site...");
            return false;
        } catch (HttpException ex) {
            setStatusCode("Http Status code:N/A");
            setOuput("Output:HttpException occured..." + ex.toString());
        } catch (IOException ex) {
            setStatusCode("Http Status code:N/A");
            setOuput("Output:IOException occured..." + ex.toString());
        }
        return false;
    }

    /**
     * @return the m_ouput
     */
    public String getOutput() {
        return m_output;
    }

    /**
     * @param m_ouput the m_ouput to set
     */
    public void setOuput(String ouput) {
        this.m_output = StringUtils.ClearHTMLTags(ouput, -1);
        m_output = StringUtils.trimAll(m_output);
        m_output = m_output.replace("\n",
                "");
        m_output = m_output.replace("\r",
                "");
    }

    /**
     * @return the m_statusCode
     */
    public String getStatusCode() {
        return m_statusCode;
    }

    /**
     * @param m_statusCode the m_statusCode to set
     */
    public void setStatusCode(String statusCode) {
        this.m_statusCode = statusCode;
    }
}
